/* typehints:start */
import { GameRoot } from "../root";
/* typehints:end */

import { createLogger } from "../../core/utils/logging";
import { People } from "../people";
import { Dialogue } from "./dialogue";
import { getPresitgeTitle } from "../defines/presitge_define";
import { getObjectType, keepDecimal, ObjectDeleteValArray0, ObjectMapCb, ObjectNeedKey } from "../../core/utils/utils";
import { getMonthTime, getYearTime } from "../time";

const logger = createLogger('game/npc')

export class NpcAttr{
  constructor(data = {}){
		// 模式：0和平，1战斗
		// 和平模式下不会进行任何攻击行为，可以对话
		// 战斗模式下会进行战斗进度条，当进度条满了之后就会对你进行攻击
		this.mode = data.mode || 0;
    // 是否需要保存数据
    this.isSave = data.isSave !== undefined ? data.isSave : true;
		// 是否在世界上存在
		this.isLive = data.isLive !== undefined ? data.isLive : true;
		// 背包
		this.backdropGoods = data.backdropGoods || [];
		this.backdropShops = data.backdropShops || [];
		this.shopOnlyItem = data.shopOnlyItem || [];
		// 商店上次更新时间
		this.shopUpdateTime = data.shopUpdateTime || -1000;
  }
}

export class Npc {
	constructor(root, storeId, attachPeopleAttr = {}, attachNpcAttr = {}, isGenerate = false) {
		// 在地图编辑器中的编号，全局唯一
    this.storeId = storeId;
		// 生成Npc时，附加在生灵属性的内容
    this.attachPeopleAttr = attachPeopleAttr;
		// 生成Npc时，附加在Npc属性的内容
    this.attachNpcAttr = attachNpcAttr;
		// 是否为系统自动生成物品，如果是，那么将会记录在存档中
		this.isGenerate = isGenerate;

    /** @type {People} */
		this.people = null;

		/** @type {GameRoot} */
		this.root = root;

    /** @type {NpcAttr} */
    this.attr = null;

		/** @type {HTMLElement} */
		this.element = null;

    this.dialogue = new Dialogue(this);

		// 战斗进度，当100时进入战斗
		this.battleProgress = 0;
	}

	initialize() {
    let saveData = this.root.itemData.npcData[this.storeId];
		let backdrop = this.backdropDefine()(this);
		this.attachNpcAttr.backdropGoods = backdrop.goods;

    if(saveData){
      this.people = new People(this.root, { 
				name: this.getName(),
				...this.getPeopleAttr(), ...this.attachPeopleAttr, ...ObjectDeleteValArray0(saveData.peopleAttr)
			});
      this.attr = new NpcAttr({ ...this.getNpcAttr(), ...this.attachNpcAttr, ...(saveData.npcAttr) });
    } else {
      this.people = new People(this.root, Object.assign(this.getPeopleAttr(), {
        name: this.getName()
      }, this.attachPeopleAttr));
      this.attr = new NpcAttr(Object.assign(this.getNpcAttr(), this.attachNpcAttr));
    }

    this.saveNpcData();
	}

  /**
   * 修改npc的数据，并保存
   * @param {*} cb 
   */
  saveNpcData(cb){
    cb && cb(this.people.data, this.attr);

    if(!this.attr.isSave) {
			return;
		}
    
    this.root.itemData.npcData[this.storeId] = {
      peopleAttr: ObjectNeedKey(this.people.internalGetData(), ['worldPos', 'mapPos', 'money', 'stone', 'practiceDiff', 'attrDiff']),
      npcAttr: this.attr
    }
    this.root.saveItemData();
  }

	getName() {
		abstract;
	}

	setFavor(num){
		this.saveNpcData(peopleAttr => {
			peopleAttr.favor += num;
		})
		this.root.message('infos', [
			`${this.getName()}对你好感${num > 0 ? '增加' : '降低'}${num}点`
		])
	}

	// 聊天第一句定义
	messageDefine(){
		return () => {}
	}

  getNpcAttr(){
		return {};
  }

	/**
	 * 生灵的基本属性数据
	 */
	getPeopleAttr() {
		abstract;
	}

	addBattleProgress() {
		let currentNpc = this.root.worldMap.getCurrentNpcs().find(item => {
			if(item == this) return true;
		});

		if(currentNpc){
			this.battleProgress += keepDecimal(1, 1);
		} else {
			this.battleProgress -= keepDecimal(1, 1);
		}

		if (this.battleProgress >= 100) {
			this.battleProgress = 100;
		} else if(this.battleProgress <= 0){
			this.battleProgress = 0;
		}

		if(this.element){
			this.element.querySelector(".progres span").innerHTML = `${this.battleProgress}/100`;

			if(this.attr.mode == 1){
				this.element.classList.remove('white');
				this.element.classList.add('danger');
			} else {
				this.element.classList.add('white');
				this.element.classList.remove('danger');
			}
		}
	}

	getControls() {
		return [];
	}

	defineDialogue(dialogues) {
		this.dialogues.concat(dialogues);
	}

	getMessage() {
		return this.internalGetMessage();
	}

	// 是否拒绝被拉入战斗，不被相同种族影响，拒绝拉入战斗
	getIsRefuseBattle(){
		return false;
	}

	// 直接判定为我方单位
	getIsMeBattle(){
		return false;
	}
	
	/**
	 * 人物背包及商店物品
	 * @returns 
	 */
	backdropDefine(){
		return () => ({ shops: [], goods: [] })
	}

	/**
	 * 是否拥有商店功能
	 * @returns 
	 */
	getIsShop(){
		return false;
	}

	/**
	 * 特价商品
	 * {
	 * 		key: '',
	 *    // 价格比例
	 * 		sold: .7
	 * }
	 * @returns 
	 */
	getShopSpecialDiscount(){
		return {};
	}

	/**
	 * 商店更新周期，默认一年
	 */
	getShopUpdateTime(){
		return getYearTime();
	}

	/**
	 * 返回npc使用什么样的战斗ai
	 * @returns 
	 */
	getBattleAi(){
		return 'BasicAi';
	}
  
  // 定义所有可显示的对话
  dialogueDefine(){
    return () => {}
  }

	update(){
    this.root.time.run(`npc-update-${this.people.data._id}`, () => {
			// 战斗模式更新警惕值
			if(this.attr.mode == 1){
				this.addBattleProgress();
			}

			// 更新店铺商品，只有当npc在世界存在、唯一Id存在的时候才会被更新
			if(this.getIsShop() && this.storeId && this.attr.isLive){
				if(new Date().getTime() - this.attr.shopUpdateTime >= this.getShopUpdateTime()){
					this.saveNpcData((peopleAttr, npcAttr) => {
						this.internalUpdateShop();
						npcAttr.shopUpdateTime = new Date().getTime();
					})
				}
			} else if(this.getIsShop() && !this.storeId){
				assert(false, `对Npc${this.getName()}开放了商铺，但该Npc无法保存内容`);
			}
    }, 100);
	}

	/**
	 * --------------------   Npc内部方法   ----------------------
	 */

	internalGetMessage() {
		let messages = this.messageDefine()(this);
		let type = Math.random() > .4 && messages['special'].length > 0 ? 'special' : 'normal';
		messages = messages[type];

		if (messages.length > 0) {
			return messages[~~(messages.length * Math.random())];
		} else {
			return "我没有什么好说的...";
		}
	}

	internalDestory(){
		this.saveNpcData((peopleAttr, attr) => {
			attr.isLive = false;
		})

		// 重新绘制
		this.root.hud.parts.worldPage.renderAllPeopleAndGoods();
		this.root.hud.parts.npcBoard.hanldeHideNpcBoard();

		if(this.isGenerate){
			let storeData = this.root.worldData.mapItem[this.storeId];
			storeData.num = storeData.num - 1;
			this.root.saveWorldData();
		}
	}

	internalUpdateShop(){
		let backdrop = this.backdropDefine()(this);
		let items = backdrop.shops.filter(item => {
			if(item.only && this.attr.shopOnlyItem.indexOf(item.key) > -1){
				return false;
			}
			return true;
		});
		
		this.saveNpcData((peopleAttr, npcAttr) => {
			items.map(item => {
				Object.keys(item).map(key => {
					if(getObjectType(item[key]) == 'Function' || key == 'buyTip'){
						delete item[key];
					}
				})
			})
			npcAttr.backdropShops = items;
		})

		let shopBoard = this.root.hud.parts.shopBoard;
		if(shopBoard.npc == this && shopBoard.domAttach.attached){
			this.root.message('alert', '商品已更新');
			shopBoard.renderItems();
		}
	}

	/**
	 * 执行操作需要的必须数据，执行等待时间、副业必须等级
	 */
	internalGetControl() {
		let data = [];
		let controls = this.getControls().map(item => {
			let key = item.key;
			
			let confirmFn = this[`getIs${key}Confirm`];

			// 重复确认是否这个操作
			item.confirm = confirmFn ? confirmFn() : false;

			return item;
		});

		for (let i = 0; i < controls.length; i++) {
			let item = controls[i];
			let fn = this[`getControl${item.key}`];
			let conditionFn = this[`getControl${item.key}Condition`];
			if (fn && (!conditionFn || conditionFn.call(this)))
				data.push({
					...item,
					fn
				});
		}

		return data;
	}
}